package com.adcc.loadsheet.monitor.service;

import com.adcc.aoc.devLib.common.log.Log;
import com.adcc.aoc.devLib.traffic.mq.manage.active.ActiveMQManager;
import com.adcc.aoc.devLib.traffic.mq.manage.active.ActiveQueue;
import com.adcc.aoc.devLib.traffic.mq.manage.active.ActiveTopic;
import com.adcc.loadsheet.monitor.congifuration.AppConfiguration;
import com.adcc.loadsheet.monitor.congifuration.OracleMasterDataSourceConfiguration;
import com.adcc.loadsheet.monitor.congifuration.OracleSlaveDataSourceConfiguration;
import com.adcc.loadsheet.monitor.entity.*;
import com.adcc.loadsheet.monitor.mapper.mysql.ServerLogMapper;
import com.adcc.loadsheet.monitor.mapper.oracle.master.MasterSystemMapper;
import com.adcc.loadsheet.monitor.mapper.oracle.slave.SlaveSystemMapper;
import com.adcc.loadsheet.monitor.util.*;
import com.adcc.loadsheet.monitor.vo.MonitorServerVO;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Minutes;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

@Service("MonitorService")
public class MonitorServiceImpl implements MonitorService {

    @Autowired
    private AppConfiguration appConfiguration;

    @Autowired
    private ServerLogService logService;

    @Autowired
    private SystemConfigFactory systemConfigFactory;

    @Autowired
    @Qualifier("oracleMasterDataSourceConfiguration")
    private OracleMasterDataSourceConfiguration masterDataSourceConfiguration;

    @Autowired
    @Qualifier("oracleSlaveDataSourceConfiguration")
    private OracleSlaveDataSourceConfiguration slaveDataSourceConfiguration;

    @Autowired
    private MasterSystemMapper masterSystemMapper;

    @Autowired
    private SlaveSystemMapper slaveSystemMapper;

    @Autowired
    private AppUploadUDPFactory appUploadUDPFactory;

    @Autowired
    private MsgUpCenterUDPFactory msgUpCenterUDPFactory;

    @Autowired
    private ServerLogMapper serverLogMapper;

    // 监控系统信息
    private MonitorServer server = new MonitorServer();

    /**
     * 计算磁盘使用率（百分比）
     *
     * @param json
     * @return
     */
    private double getDiskUsage(String json) {
        double diskUsage = 0.0D;
        try {
            if (!Strings.isNullOrEmpty(json)) {
                JSONObject obj = JSON.parseObject(json);
                if (obj.containsKey("diskSpace")) {
                    JSONObject diskSpace = obj.getJSONObject("diskSpace");
                    long total = diskSpace.getLong("total");
                    long free = diskSpace.getLong("free");
                    long used = total - free;
                    diskUsage = Math.round(((double) used / (double) total) * 10000D) / 100D;
                }
            }
        } catch (Exception ex) {
            Log.error(MonitorService.class, "getDiskUsage() error", ex);
        }
        return diskUsage;
    }

    /*
    BGS接口返回结果：
    String json = "{\n" +
                        "  \"bgs\" : {\n" +
                        "    \"healthy\" : true,\n" +
                        "    \"message\" : \"{\\\"version\\\":\\\"3.3.0\\\",\\\"name\\\":\\\"BGS2\\\",\\\"host\\\":\\\"127.0.0.1\\\",\\\"gcs\\\":{\\\"id\\\":\\\"BGS2\\\",\\\"ip\\\":\\\"127.0.0.1\\\",\\\"agsName\\\":\\\"GW1A\\\",\\\"master\\\":{\\\"state\\\":\\\"CONNECTED\\\",\\\"updateTime\\\":\\\"2020-04-04 07:18:34\\\",\\\"available\\\":true},\\\"available\\\":true,\\\"updateTime\\\":\\\"2020-04-07 07:30:23\\\"},\\\"mq\\\":{\\\"master\\\":{\\\"url\\\":\\\"tcp://192.168.241.211:61616\\\",\\\"state\\\":\\\"CONNECTED\\\",\\\"updateTime\\\":\\\"2020-03-25 06:50:38\\\"},\\\"available\\\":true,\\\"updateTime\\\":\\\"2020-03-25 06:50:38\\\"},\\\"redis\\\":{\\\"host\\\":\\\"127.0.0.1\\\",\\\"port\\\":6379,\\\"available\\\":true},\\\"downlink\\\":{\\\"count\\\":21,\\\"updateTime\\\":\\\"2020-04-14 03:32:49\\\",\\\"active\\\":true},\\\"uplink\\\":{\\\"count\\\":12,\\\"updateTime\\\":\\\"2020-04-14 03:32:48\\\",\\\"active\\\":true}}\"\n" +
                        "  },\n" +
                        "  \"deadlocks\" : {\n" +
                        "    \"healthy\" : true\n" +
                        "  }\n" +
                        "}";*/
    @Override
    public void monitorBGS() {
        try {
            // 获取BGS服务监控状态
            BGSMonitor bgs = server.getBgs() != null ? (BGSMonitor) server.getBgs().clone() : new BGSMonitor();
            String healthCheckUrl = Strings.nullToEmpty((String) systemConfigFactory.getBgsConfigMap().get("healthCheck"));
            String json = RestClient.get(healthCheckUrl);
            if (!Strings.isNullOrEmpty(json)) {
                try {
                    Map<String, Object> map = JSON.parseObject(json, Map.class);

                    // 解析bgs信息
                    Map<String, Object> bgsInfo = (Map<String, Object>) map.get("bgs");
                    // bgs状态
                    bgs.setStatus((boolean) bgsInfo.get("healthy") ? MonitorStatus.NORMAL : MonitorStatus.ABNORMAL);

                    // 解析bgs的message
                    String bgsMessage = bgsInfo.get("message").toString();
                    Map<String, Object> bgsDetailInfo = JSON.parseObject(bgsMessage, Map.class);
                    // 解析BGS地址
                    bgs.setHost(bgsDetailInfo.get("host").toString());
                    // 解析BGS网关名称
                    bgs.setName(bgsDetailInfo.get("name").toString());

                    // 解析AGS信息
                    Map<String, Object> agsInfo = (Map<String, Object>) bgsDetailInfo.get("gcs");
                    bgs.setAgsStatus((boolean) agsInfo.get("available"));

                    // 解析ActiveMQ信息
                    Map<String, Object> mqInfo = (Map<String, Object>) bgsDetailInfo.get("mq");
                    bgs.setMqStatus((boolean) mqInfo.get("available"));

                    // 解析下行报
                    Map<String, Object> downlinkInfo = (Map<String, Object>) bgsDetailInfo.get("downlink");
                    bgs.setDownlinkStatus((boolean) downlinkInfo.get("active") ? MonitorStatus.NORMAL : MonitorStatus.WARNING);
                    bgs.setDownlinkUpdateTime((String) downlinkInfo.get("updateTime"));

                    // 解析上行报
                    Map<String, Object> uplinkInfo = (Map<String, Object>) bgsDetailInfo.get("uplink");
                    bgs.setUplinkStatus((boolean) uplinkInfo.get("active") ? MonitorStatus.NORMAL : MonitorStatus.WARNING);
                    bgs.setUplinkUpdateTime((String) uplinkInfo.get("updateTime"));

                    // AGS状态或者MQ状态为false，则bgs状态为ABNORMAL
                    if (!bgs.isAgsStatus() || !bgs.isMqStatus()) {
                        bgs.setStatus(MonitorStatus.ABNORMAL);
                    }

                    // 当bgs状态正常时（即MQ和AGS状态为true），下行状态或者上行状态为false，则bgs状态为WARNING
                    if (bgs.getStatus() == MonitorStatus.NORMAL && (!MonitorStatus.NORMAL.equals(bgs.getDownlinkStatus()) || !MonitorStatus.NORMAL.equals(bgs.getUplinkStatus()))) {
                        bgs.setStatus(MonitorStatus.WARNING);
                    }

                } catch (Exception ex) {
                    Log.error(MonitorService.class, "request BGS health check error", ex);
                    bgs.setStatus(MonitorStatus.ABNORMAL);
                    bgs.setAgsStatus(false);
                    bgs.setMqStatus(false);
                }
            } else {
                Log.error(MonitorService.class, "request BGS health check error");
                bgs.setStatus(MonitorStatus.ABNORMAL);
                bgs.setAgsStatus(false);
                bgs.setMqStatus(false);
            }

            if (!bgs.isMqStatus()) {
                bgs.setDownlinkStatus(MonitorStatus.ABNORMAL);
                bgs.setUplinkStatus(MonitorStatus.ABNORMAL);
            }

            // 构建异常状态码
            bgs.buildErrorCode();

            // 获取模块名
            String moduleName = AlarmEnum.MODULE_BGS.getItem();
            // 创建BGS告警日志[2024-6-01：张丽娟：增加声音和弹窗告警的功能，系统支持对指定告警项进行声音和弹窗告警忽略的功能]
            logService.buildBGSAlarmLog(moduleName, bgs, server.getBgs());

            // 创建BGS日志
            logService.buildBGSLog(moduleName, bgs, server.getBgs());

            // 更新BGS状态
            if (server.getBgs() == null) {
                server.setBgs(new BGSMonitor());
            }
            server.getBgs().setHost(bgs.getHost());
            server.getBgs().setName(bgs.getName());
            server.getBgs().setStatus(bgs.getStatus());
            server.getBgs().setMqStatus(bgs.isMqStatus());
            server.getBgs().setAgsStatus(bgs.isAgsStatus());
            server.getBgs().setDownlinkStatus(bgs.getDownlinkStatus());
            server.getBgs().setDownlinkUpdateTime(bgs.getDownlinkUpdateTime());
            server.getBgs().setUplinkStatus(bgs.getUplinkStatus());
            server.getBgs().setUplinkUpdateTime(bgs.getUplinkUpdateTime());
            server.getBgs().setErrorCode(bgs.getErrorCode());
            server.getBgs().setUnAlarmContent(bgs.getUnAlarmContent());
            server.getBgs().setAlarmContent(bgs.getAlarmContent());
        } catch (Exception ex) {
            Log.error(MonitorService.class, "monitorBGS() error", ex);
        }
    }

    @Override
    public void monitorDatabase() {
        try {
            // 获取Database监控状态
            DatabaseMonitor database = server.getDatabase() != null ? (DatabaseMonitor) server.getDatabase().clone() : new DatabaseMonitor();
            // 获取主备数据库的ip
            String masterIp = StringUtil.getIP(masterDataSourceConfiguration.getUrl());
            database.setMasterIp(masterIp);
            String slaveIp = StringUtil.getIP(slaveDataSourceConfiguration.getUrl());
            database.setSlaveIp(slaveIp);

            // 数据库进程比告警阀值
            double warn = Double.valueOf((String) systemConfigFactory.getDatabaseConfigMap().get("warn"));
            // 数据库进程比异常阀值
            double error = Double.valueOf((String) systemConfigFactory.getDatabaseConfigMap().get("error"));
            // 磁盘使用率告警阀值
            double diskUsage = Double.valueOf((String) systemConfigFactory.getDatabaseConfigMap().get("diskUsage"));
            // 表空间使用率告警阀值
            double tablespaceUsage = Double.valueOf((String) systemConfigFactory.getDatabaseConfigMap().get("tablespaceUsage"));

            // 获取主数据库的监控信息
            try {
                if (masterSystemMapper.validate() == 1) {
                    database.setMasterStatus(MonitorStatus.NORMAL);
                    int masterActiveProcess = masterSystemMapper.getActiveProcess();
                    database.setMasterActiveProcess(masterActiveProcess);
                    int masterMaxProcess = masterSystemMapper.getMaxProcess();
                    database.setMasterMaxProcess(masterMaxProcess);
                    double masterProcessUsage = Math.round(((double) masterActiveProcess / (double) masterMaxProcess) * 10000D) / 100D;
                    database.setMasterProcessUsage(masterProcessUsage);
                    double masterTablespaceUsage = masterSystemMapper.getTablespaceUsage(appConfiguration.getTablespaceName());
                    database.setMasterTablespaceUsage(masterTablespaceUsage);
                } else {
                    database.setMasterActiveProcess(0);
                    database.setMasterMaxProcess(0);
                    database.setMasterProcessUsage(0.0D);
                    database.setMasterTablespaceUsage(0.0D);
                    database.setMasterStatus(MonitorStatus.ABNORMAL);
                }
            } catch (Exception ex) {
                Log.error(MonitorService.class, "monitor master database error", ex);
                database.setMasterActiveProcess(0);
                database.setMasterMaxProcess(0);
                database.setMasterProcessUsage(0.0D);
                database.setMasterTablespaceUsage(0.0D);
                database.setMasterStatus(MonitorStatus.ABNORMAL);
            }
            try {
                if (slaveSystemMapper.validate() == 1) {
                    database.setSlaveStatus(MonitorStatus.NORMAL);
                    int slaveActiveProcess = slaveSystemMapper.getActiveProcess();
                    database.setSlaveActiveProcess(slaveActiveProcess);
                    int slaveMaxProcess = slaveSystemMapper.getMaxProcess();
                    database.setSlaveMaxProcess(slaveMaxProcess);
                    double slaveProcessUsage = Math.round(((double) slaveActiveProcess / (double) slaveMaxProcess) * 10000D) / 100D;
                    database.setSlaveProcessUsage(slaveProcessUsage);
                    double slaveTablespaceUsage = slaveSystemMapper.getTablespaceUsage(appConfiguration.getTablespaceName());
                    database.setSlaveTablespaceUsage(slaveTablespaceUsage);
                } else {
                    database.setSlaveActiveProcess(0);
                    database.setSlaveMaxProcess(0);
                    database.setSlaveProcessUsage(0.0D);
                    database.setSlaveTablespaceUsage(0.0D);
                    database.setSlaveStatus(MonitorStatus.ABNORMAL);
                }
            } catch (Exception ex) {
                Log.error(MonitorService.class, "monitor slave database error", ex);
                database.setSlaveActiveProcess(0);
                database.setSlaveMaxProcess(0);
                database.setSlaveProcessUsage(0.0D);
                database.setSlaveTablespaceUsage(0.0D);
                database.setSlaveStatus(MonitorStatus.ABNORMAL);
            }

            // 获取Agent信息，计算磁盘使用率
            String masterAgentUrl = String.format(appConfiguration.getAgentUrl(), masterIp);
            String masterJson = RestClient.get(masterAgentUrl);
            double masterDiskUsage = getDiskUsage(masterJson);
            database.setMasterDiskUsage(masterDiskUsage);

            String slaveAgentUrl = String.format(appConfiguration.getAgentUrl(), slaveIp);
            String slaveJson = RestClient.get(slaveAgentUrl);
            double slaveDiskUsage = getDiskUsage(slaveJson);
            database.setSlaveDiskUsage(slaveDiskUsage);

            // 判断主数据库数据状态
            // 进程比
            if (MonitorStatus.NORMAL == database.getMasterStatus()) {
                if (database.getMasterProcessUsage() < warn) {
                    database.setMasterStatus(MonitorStatus.NORMAL);
                } else if (database.getMasterProcessUsage() < error) {
                    database.setMasterStatus(MonitorStatus.WARNING);
                } else {
                    database.setMasterStatus(MonitorStatus.ABNORMAL);
                }
            }
            // 表空间使用率
            if (MonitorStatus.NORMAL == database.getMasterStatus()) {
                if (database.getMasterTablespaceUsage() > tablespaceUsage) {
                    database.setMasterStatus(MonitorStatus.WARNING);
                }
            }
            // 磁盘使用率
            if (MonitorStatus.NORMAL == database.getMasterStatus()) {
                if (database.getMasterDiskUsage() > diskUsage) {
                    database.setMasterStatus(MonitorStatus.WARNING);
                }
            }

            // 判断从数据库数据状态
            // 进程比
            if (MonitorStatus.NORMAL == database.getSlaveStatus()) {
                if (database.getSlaveProcessUsage() < warn) {
                    database.setSlaveStatus(MonitorStatus.NORMAL);
                } else if (database.getSlaveProcessUsage() < error) {
                    database.setSlaveStatus(MonitorStatus.WARNING);
                } else {
                    database.setSlaveStatus(MonitorStatus.ABNORMAL);
                }
            }
            // 表空间使用率
            if (MonitorStatus.NORMAL == database.getSlaveStatus()) {
                if (database.getSlaveTablespaceUsage() > tablespaceUsage) {
                    database.setSlaveStatus(MonitorStatus.WARNING);
                }
            }
            // 磁盘使用率
            if (MonitorStatus.NORMAL == database.getSlaveStatus()) {
                if (database.getSlaveDiskUsage() > diskUsage) {
                    database.setSlaveStatus(MonitorStatus.WARNING);
                }
            }

            // 判断数据库整体状态
            if (MonitorStatus.NORMAL == database.getMasterStatus() && MonitorStatus.NORMAL == database.getSlaveStatus()) {
                database.setStatus(MonitorStatus.NORMAL);
            } else if (MonitorStatus.ABNORMAL == database.getMasterStatus()) {
                database.setStatus(MonitorStatus.ABNORMAL);
            } else {
                database.setStatus(MonitorStatus.WARNING);
            }

            // 构建异常状态码
            database.buildErrorCode();

            // 获取模块名
            String moduleName = AlarmEnum.MODULE_DATABASE.getItem();
            // 创建Database告警日志[2024-6-01：张丽娟：增加声音和弹窗告警的功能，系统支持对指定告警项进行声音和弹窗告警忽略的功能]
            logService.buildDatabaseAlarmLog(moduleName, database, server.getDatabase());

            // 创建Database日志
            logService.buildDatabaseLog(moduleName, database, server.getDatabase());

            // 更新Database状态
            server.setDatabase(database);

        } catch (Exception ex) {
            Log.error(MonitorService.class, "monitorDatabase() error", ex);
        }
    }

    @Override
    public void monitorMQ() {
        try {
            // 获取MQ监控信息
            MQMonitor mq = server.getMq() != null ? (MQMonitor) server.getMq().clone() : new MQMonitor();

            // 获取配置信息
            String url = (String) systemConfigFactory.getMqConfigMap().get("url");
            String uplinkTopic = (String) systemConfigFactory.getMqConfigMap().get("uplinkTopic");
            String downlinkTopic = (String) systemConfigFactory.getMqConfigMap().get("downlinkTopic");

            // 设置mq基本信息
            String ip = StringUtil.getIP(url);
            mq.setIp(ip);
            mq.setUplinkTopic(uplinkTopic);
            mq.setDownlinkTopic(downlinkTopic);

            // 连接JMX，获取JMX信息
            try {
                ActiveMQManager<ActiveQueue, ActiveTopic> manager = new ActiveMQManager<ActiveQueue, ActiveTopic>(url);
                // 获取上行TOPIC
                List<ActiveTopic> uplinkList = manager.findTopic(uplinkTopic);
                if (uplinkList != null && uplinkList.size() > 0) {
                    ActiveTopic uplink = uplinkList.get(0);
                    mq.setUplinkTopicConsumerNum(uplink.getConsumers());
                    mq.setUnlinkTopicEnqueued(uplink.getEnqueued());
                } else {
                    mq.setUplinkTopicConsumerNum(0L);
                    mq.setUnlinkTopicEnqueued(0L);
                }

                // 获取下行TOPIC
                List<ActiveTopic> downlinkList = manager.findTopic(downlinkTopic);
                if (downlinkList != null && downlinkList.size() > 0) {
                    ActiveTopic downlink = downlinkList.get(0);
                    mq.setDownlinkTopicConsumerNum(downlink.getConsumers());
                    mq.setDownlinkTopicEnqueued(downlink.getEnqueued());
                } else {
                    mq.setDownlinkTopicConsumerNum(0L);
                    mq.setDownlinkTopicEnqueued(0L);
                }

                mq.setStatus(MonitorStatus.NORMAL);
            } catch (Exception e) {
                Log.error(MonitorService.class, "MQ JMX connected error!", e);
                mq.setUplinkTopicConsumerNum(0L);
                mq.setUnlinkTopicEnqueued(0L);
                mq.setDownlinkTopicConsumerNum(0L);
                mq.setDownlinkTopicEnqueued(0L);
                mq.setStatus(MonitorStatus.ABNORMAL);
            }

            // 构建异常状态码
            mq.buildErrorCode();

            // 获取模块名
            String moduleName = AlarmEnum.MODULE_MQ.getItem();
            // 创建MQ告警日志[2024-6-01：张丽娟：增加声音和弹窗告警的功能，系统支持对指定告警项进行声音和弹窗告警忽略的功能]
            logService.buildMQAlarmLog(moduleName, mq, server.getMq());

            // 创建MQ日志
            logService.buildMQLog(moduleName, mq, server.getMq());

            // 更新MQ状态
            server.setMq(mq);

        } catch (Exception ex) {
            Log.error(MonitorService.class, "monitorMQ() error", ex);
        }
    }

    @Override
    public void monitorAppUpload() {
        try {
            // 获取当前AppUpload监控信息
            AppUploadMonitor appUpload = (AppUploadMonitor) appUploadUDPFactory.getMonitor().clone();

            // 构建异常状态码
            appUpload.buildErrorCode();

            // 获取模块名
            String moduleName = AlarmEnum.MODULE_APP_UPLOAD.getItem();
            // 创建AppUpload告警日志[2024-6-01：张丽娟：增加声音和弹窗告警的功能，系统支持对指定告警项进行声音和弹窗告警忽略的功能]
            logService.buildAppUploadAlarmLog(moduleName, appUpload, server.getAppUpload());

            // 创建AppUpload日志
            logService.buildAppUploadLog(moduleName, appUpload, server.getAppUpload());

            // 更新监控中AppUpload信息
            server.setAppUpload(appUpload);

        } catch (Exception ex) {
            Log.error(MonitorService.class, "monitorAppUpload() error", ex);
        }
    }

    @Override
    public void monitorAirInfo() {
        try {
            AirInfoMonitor airInfo = server.getAirInfo() != null ? (AirInfoMonitor) server.getAirInfo().clone() : new AirInfoMonitor();

            // 获取航信接口配置
            String url = (String) systemConfigFactory.getAirInfoConfigMap().get("url");
            String topicName = (String) systemConfigFactory.getAirInfoConfigMap().get("topic");
            List<MsgAlarmConfig> msgAlarmConfigList = (List<MsgAlarmConfig>) systemConfigFactory.getAirInfoConfigMap().get("msgAlarm");

            // 航信接口MQ JMX连接
            try {
                ActiveMQManager<ActiveQueue, ActiveTopic> manager = new ActiveMQManager<ActiveQueue, ActiveTopic>(url);
                List<ActiveTopic> topicList = manager.findTopic(topicName);
                // 设置mq连接状态
                airInfo.setMqStatus(true);

                DateTime now = DateTime.now(DateTimeZone.UTC);
                if (topicList != null && topicList.size() > 0) {
                    ActiveTopic topic = topicList.get(0);
                    // 第一次获取监控信息或者入TOPIC消息数量变化时，设置报文更新时间
                    if (server.getAirInfo() == null || (topic.getEnqueued() != server.getAirInfo().getEnqueued())) {
                        airInfo.setEnqueued(topic.getEnqueued());
                        airInfo.setUpdateTime(now);
                    }

                    // 判断各个时间段的舱单报文告警状态
                    for (MsgAlarmConfig config : msgAlarmConfigList) {
                        // startTime endTime nowTime 默认日期为1970-01-01
                        DateTime startTime = DateTime.parse(config.getStartTime(), DateTimeFormat.forPattern("HH:mm"));
                        DateTime endTime = DateTime.parse(config.getEndTime(), DateTimeFormat.forPattern("HH:mm"));
                        long timeout = Long.valueOf(config.getTimeout());
                        DateTime nowTime = DateTime.parse(now.toString("HH:mm"), DateTimeFormat.forPattern("HH:mm"));
                        // 如果开始时间在结束时间之前，则结束时间+1天（处理跨天情况）
                        if (startTime.isAfter(endTime)) {
                            endTime = endTime.plusDays(1);
                            // 如果当前时间在开始时间之前，则当前时间+1天（处理跨天情况）
                            if (nowTime.isBefore(startTime)) {
                                nowTime = nowTime.plusDays(1);
                            }
                        }
                        // 在当前时间段内，根据当前时间与上一次报文更新时间，计算无报文时间差
                        if (nowTime.isAfter(startTime) && !nowTime.isAfter(endTime)) {
                            if (server.getAirInfo() == null) {
                                airInfo.setNoReceiveTime(0L);
                                // 第一次默认topic状态为true
                                airInfo.setTopicStatus(true);
                            } else {
                                // 计算无报文时间差
                                long diff = Minutes.minutesBetween(server.getAirInfo().getUpdateTime(), now).getMinutes();
                                airInfo.setNoReceiveTime(diff);
                                airInfo.setTopicStatus(diff <= timeout);
                            }
                            break;
                        }
                    }
                } else {
                    // 无topic
                    airInfo.setTopicStatus(false);

                    // 第一次监控，设置初始的更新时间和无报文时间
                    if (server.getAirInfo() == null) {
                        airInfo.setUpdateTime(now);
                        airInfo.setNoReceiveTime(0L);
                    } else {
                        // 计算无报文时间
                        long diff = Minutes.minutesBetween(server.getAirInfo().getUpdateTime(), now).getMinutes();
                        airInfo.setNoReceiveTime(diff);
                    }
                }
            } catch (Exception e) {
                Log.error(MonitorService.class, "AirInfo JMX connected error!", e);
                airInfo.setMqStatus(false);
                airInfo.setTopicStatus(false);
                airInfo.setStatus(MonitorStatus.ABNORMAL);
                // 第一次监控，设置初始的更新时间和无报文时间
                if (server.getAirInfo() == null) {
                    airInfo.setUpdateTime(DateTime.now(DateTimeZone.UTC));
                    airInfo.setNoReceiveTime(0L);
                } else {
                    // 计算无报文时间
                    long diff = Minutes.minutesBetween(server.getAirInfo().getUpdateTime(), DateTime.now(DateTimeZone.UTC)).getMinutes();
                    airInfo.setNoReceiveTime(diff);
                }
            }

            // 判断整体状态
            if (airInfo.isMqStatus() && airInfo.isTopicStatus()) {
                airInfo.setStatus(MonitorStatus.NORMAL);
            } else {
                airInfo.setStatus(MonitorStatus.ABNORMAL);
            }

            // 构建异常状态码
            airInfo.buildErrorCode();

            // 获取模块名
            String moduleName = AlarmEnum.MODULE_AIR_INFO.getItem();
            // 创建航信接口告警日志[2024-6-01：张丽娟：增加声音和弹窗告警的功能，系统支持对指定告警项进行声音和弹窗告警忽略的功能]
            logService.buildAirInfoAlarmLog(moduleName, airInfo, server.getAirInfo());

            // 创建航信接口日志
            logService.buildAirInfoLog(moduleName, airInfo, server.getAirInfo());

            // 更新航信接口状态
            server.setAirInfo(airInfo);

        } catch (Exception ex) {
            Log.error(MonitorService.class, "monitorAirInfo() error", ex);
        }
    }

    @Override
    public void monitorMsgUpCenter() {
        try {
            // 获取当前MsgUpCenter监控信息
            MsgUpCenterMonitor msgUpCenter = (MsgUpCenterMonitor) msgUpCenterUDPFactory.getMonitor().clone();

            // 构建异常状态码
            msgUpCenter.buildErrorCode();

            // 获取模块名
            String moduleName = AlarmEnum.MODULE_MSG_UP_CENTER.getItem();
            // 创建MsgUpCenter告警日志[2024-6-01：张丽娟：增加声音和弹窗告警的功能，系统支持对指定告警项进行声音和弹窗告警忽略的功能]
            logService.buildMsgUpCenterAlarmLog(moduleName, msgUpCenter, server.getMsgUpCenter());

            // 创建MsgUpCenter日志
            logService.buildMsgUpCenterLog(moduleName, msgUpCenter, server.getMsgUpCenter());

            // 更新监控中的MsgUpCenter信息
            server.setMsgUpCenter(msgUpCenter);

        } catch (Exception ex) {
            Log.error(MonitorService.class, "monitorAppUpload() error", ex);
        }
    }

    @Override
    public void monitorWebsite() {
        try {
            WebsiteMonitor website = server.getWebsite() != null ? (WebsiteMonitor) server.getWebsite().clone() : new WebsiteMonitor();

            String url1 = (String) systemConfigFactory.getWebsiteConfigMap().get("url1");
            website.setUrl1(url1);
            website.setConnectStatus1(RestClient.connect(url1));

            String url2 = (String) systemConfigFactory.getWebsiteConfigMap().get("url2");
            website.setUrl2(url2);
            website.setConnectStatus2(RestClient.connect(url2));

            if (website.isConnectStatus1() && website.isConnectStatus2()) {
                website.setStatus(MonitorStatus.NORMAL);
            } else if (!website.isConnectStatus1() && !website.isConnectStatus2()) {
                website.setStatus(MonitorStatus.ABNORMAL);
            } else {
                website.setStatus(MonitorStatus.WARNING);
            }

            // 构建异常状态码
            website.buildErrorCode();

            // 获取模块名
            String moduleName = AlarmEnum.MODULE_WEBSITE.getItem();
            // 创建website告警日志[2024-6-01：张丽娟：增加声音和弹窗告警的功能，系统支持对指定告警项进行声音和弹窗告警忽略的功能]
            logService.buildWebsiteAlarmLog(moduleName, website, server.getWebsite());

            // 创建website日志
            logService.buildWebsiteLog(moduleName, website, server.getWebsite());

            // 更新website状态
            server.setWebsite(website);

        } catch (Exception ex) {
            Log.error(MonitorService.class, "getMonitorServer() error", ex);
        }
    }

    @Override
    public void monitorForwarder() {
        try {
            ForwarderMonitor forwarder = server.getForwarder() != null ? (ForwarderMonitor) server.getForwarder().clone() : new ForwarderMonitor();
            String healthUrl1 = (String) systemConfigFactory.getForwarderConfigMap().get("healthUrl1");
            List<Boolean> firstProgram = monitorForwarderUrl(healthUrl1);
            String healthUrl2 = (String) systemConfigFactory.getForwarderConfigMap().get("healthUrl2");
            List<Boolean> secondProgram = monitorForwarderUrl(healthUrl2);
            boolean firstProgramUp = firstProgram.get(0);
            boolean firstUmeInterfaceUp = firstProgram.get(1);
            boolean secondProgramUp = secondProgram.get(0);
            boolean secondUmeInterfaceUp = secondProgram.get(1);
            forwarder.setFirstHost(StringUtil.getIP(healthUrl1));
            forwarder.setFirstProgramUp(firstProgramUp);
            forwarder.setFirstUmeInterfaceUp(firstUmeInterfaceUp);
            forwarder.setSecondHost(StringUtil.getIP(healthUrl2));
            forwarder.setSecondProgramUp(secondProgramUp);
            forwarder.setSecondUmeInterfaceUp(secondUmeInterfaceUp);
            // 设置程序状态
            if (firstProgramUp && firstUmeInterfaceUp && secondProgramUp && secondUmeInterfaceUp) {
                forwarder.setStatus(MonitorStatus.NORMAL);
            } else if (!firstProgramUp && !firstUmeInterfaceUp && !secondProgramUp && !secondUmeInterfaceUp) {
                forwarder.setStatus(MonitorStatus.ABNORMAL);
            } else {
                forwarder.setStatus(MonitorStatus.WARNING);
            }

            // 构建异常状态码
            forwarder.buildErrorCode();

            // 获取模块名
            String moduleName = AlarmEnum.MODULE_FORWARDER.getItem();
            // 创建forwarder告警日志[2024-6-01：张丽娟：增加声音和弹窗告警的功能，系统支持对指定告警项进行声音和弹窗告警忽略的功能]
            logService.buildForwarderAlarmLog(moduleName, forwarder, server.getForwarder());

            // 创建forwarder日志
            logService.buildForwarderLog(moduleName, forwarder, server.getForwarder());

            // 更新forwarder状态
            server.setForwarder(forwarder);
        } catch (Exception e) {
            Log.error(MonitorService.class, "monitorForwarder() error", e);
        }
    }

    /**
     * 调用url，将健康检查的存活结果返回
     *
     * @param healthUrl
     * @return 第一项是程序的状态，第二项是航旅接口的状态
     */
    private List<Boolean> monitorForwarderUrl(String healthUrl) {
        List<Boolean> result = Lists.newArrayListWithCapacity(2);
        try {
            String json = RestClient.get(healthUrl);
            if (!Strings.isNullOrEmpty(json)) {
                try {
                    Map<String, Object> resultMap = JSON.parseObject(json, Map.class);
                    JSONObject components = (JSONObject) resultMap.get("components");
                    JSONObject loadSheetHealth = (JSONObject) components.get("loadSheetHealth");
                    JSONObject details = (JSONObject) loadSheetHealth.get("details");
                    boolean programStatus = "UP".equals(String.valueOf(details.get("loadSheet")));
                    boolean umeInterfaceStatus = "UP".equals(String.valueOf(details.get("umeInterface")));
                    result.add(programStatus);
                    result.add(umeInterfaceStatus);
                } catch (Exception e) {
                    Log.error(MonitorService.class, "request forwarder health check error", e);
                }
            }
        } catch (Exception e) {
            Log.error(MonitorService.class, "monitorForwarderUrl() error,url is " + healthUrl, e);
        }
        if (result.isEmpty()) {
            result.add(false);
            result.add(false);
        }
        return result;
    }

    /**
     * [2024-6-26：张丽娟]
     * 监控：监控程序使用的MySQL数据库是否异常
     */
    @Override
    public void monitorMysql() {
        try {
            // 获取MySql监控信息
            MysqlMonitor mysql = server.getMysqlMonitor() != null ? (MysqlMonitor) server.getMysqlMonitor().clone() : new MysqlMonitor();

            try {
                // 连接数据库，判断数据库是否正常运行
                serverLogMapper.findSystemDate();
                mysql.setStatus(MonitorStatus.NORMAL);
            } catch (Exception e) {
                Log.error(MonitorService.class, "mysql connected error!", e);
                mysql.setStatus(MonitorStatus.ABNORMAL);
            }

            // 构建异常状态码
            mysql.buildErrorCode();

            // 获取模块名
            String moduleName = AlarmEnum.MODULE_MYSQL.getItem();
            // 创建MYSQL告警日志[2024-6-26：张丽娟：增加mysql的声音和弹窗告警的功能]
            logService.buildMysqlAlarmLog(moduleName, mysql, server.getMysqlMonitor());

            // 更新MYSQL状态
            server.setMysqlMonitor(mysql);

        } catch (Exception ex) {
            Log.error(MonitorService.class, "monitorMysql() error", ex);
        }
    }

    @Override
    public MonitorServerVO getMonitorServer() {
        try {
            return new MonitorServerVO(server);
        } catch (Exception ex) {
            Log.error(MonitorService.class, "getMonitorServer() error", ex);
            return null;
        }
    }
}
